// ContourBitmap.cpp: implementation of the CContourBitmap class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ContourBitmap.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CContourBitmap::CContourBitmap()
{
}

CContourBitmap::~CContourBitmap()
{
}

HRGN CContourBitmap::CreateRegion(COLORREF colorTransp)
{
	HRGN hrgnBitmap = NULL;

	if (m_hObject)
	{
		// Insert the bitmap into a temporary memory dc
		CDC dcMem;
		dcMem.CreateCompatibleDC(NULL);
		CBitmap* pOldBitmap = dcMem.SelectObject(this);

		if (colorTransp == CLR_DEFAULT)
		{
			// Default is the color of the topleft pixel
			colorTransp = dcMem.GetPixel(0, 0);
		}

		hrgnBitmap = InternalCreateRegion(&dcMem, colorTransp);

		dcMem.SelectObject(pOldBitmap);
		dcMem.DeleteDC();
	}
	return hrgnBitmap;
}


HRGN CContourBitmap::CreateRegion(CPoint pntTransparentColor)
{
	HRGN hrgnBitmap = NULL;

	if (m_hObject)
	{
		// Insert the bitmap into a temporary memory dc
		CDC dcMem;
		dcMem.CreateCompatibleDC(NULL);
		CBitmap* pOldBitmap = dcMem.SelectObject(this);

		// Get the color at the given position
		COLORREF colorTransp = dcMem.GetPixel(pntTransparentColor.x,
											  pntTransparentColor.y);
		// Sanity check
		if (colorTransp != -1)
		{
			hrgnBitmap = InternalCreateRegion(&dcMem, colorTransp);
		}

		dcMem.SelectObject(pOldBitmap);
		dcMem.DeleteDC();
	}
	return hrgnBitmap;
}


CSize CContourBitmap::GetSize()
{
	int cx = 0;
	int cy = 0;

	if (m_hObject)
	{
		BITMAP bmp;
		GetBitmap(&bmp);
		cx = bmp.bmWidth;
		cy = bmp.bmHeight;
	}

	return CSize(cx, cy);
}


BOOL CContourBitmap::Paint(CDC* pDC, int nXDest, int nYDest)
{
	BOOL bSuccess = FALSE;

	if (pDC->GetSafeHdc() != NULL)
	{
		if (m_hObject)
		{
			CSize sizPicture = GetSize();

			CDC dcMem;
			dcMem.CreateCompatibleDC(pDC);

			CBitmap* pOldBitmap = dcMem.SelectObject(this);
			
			bSuccess = pDC->BitBlt(nXDest, nYDest, sizPicture.cx, sizPicture.cy, &dcMem, 0, 0, SRCCOPY);

			dcMem.SelectObject(pOldBitmap);
			dcMem.DeleteDC();
		}
	}

	return bSuccess;
}

HRGN CContourBitmap::InternalCreateRegion(CDC* pDC, COLORREF colorTransp)
{
	CSize sizPicture = GetSize();

	// We start with the full rectangular region
	HRGN hrgnBitmap = ::CreateRectRgn(0, 0, sizPicture.cx, sizPicture.cy);

	BOOL bInTransparency = FALSE;  // Already inside a transparent part?
	int start_x = -1;			   // Start of transparent part

	// For all rows of the bitmap ...
	for (int y = 0; y < sizPicture.cy; y++)
	{
		// For all pixels of the current row ...
		// (To close any transparent region, we go one pixel beyond the
		// right boundary)
		for (int x = 0; x <= sizPicture.cx; x++)
		{
			BOOL bTransparent = FALSE; // Current pixel transparent?

			// Check for positive transparency within image boundaries
			if ((x < sizPicture.cx) && (colorTransp == pDC->GetPixel(x, y)))
			{
				bTransparent = TRUE;
			}

			// Does transparency change?
			if (bInTransparency != bTransparent)
			{
				if (bTransparent)
				{
					// Transparency starts. Remember x position.
					bInTransparency = TRUE;
					start_x = x;
				}
				else
				{
					// Transparency ends (at least beyond image boundaries).
					// Create a region for the transparency, one pixel high,
					// beginning at start_x and ending at the current x, and
					// subtract that region from the current bitmap region.
					// The remainding region becomes the current bitmap region.
					HRGN hrgnTransp = ::CreateRectRgn(start_x, y, x, y + 1);
					::CombineRgn(hrgnBitmap, hrgnBitmap, hrgnTransp, RGN_DIFF);
					::DeleteObject(hrgnTransp);

					bInTransparency = FALSE;
				}
			}
		}
	}

	return hrgnBitmap;
}
